/**  
* Copyright (c) 2009, Noel Lynch All rights reserved. Redistribution and use  
* in source and binary forms, with or without modification, are permitted  
* provided that the following conditions are met: Redistributions of source  
* code must retain the above copyright notice, this list of conditions and the  
* following disclaimer. Redistributions in binary form must reproduce the above  
* copyright notice, this list of conditions and the following disclaimer in the  
* documentation and/or other materials provided with the distribution. Neither  
* the name of Noel Lynch nor the names of contributors may be used to  
* endorse or promote products derived from this software without specific prior  
* written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR  
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
*/
// created by noellynch
// Jul 22, 2009

package com.sceneworker.app.input;

import java.util.ArrayList;

import com.jme.input.MouseInput;
import com.jme.math.Quaternion;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial;
import com.jme2utils.staticutils.CameraUtils;
import com.sceneworker.app.globals.SceneWorkerGlobals;
import com.sceneworker.app.undo.SceneWorkerAppUndoManager;
import com.sceneworker.app.undo.SpatialRotationUndoAction;
import com.sceneworker.app.undo.SpatialScaleUndoAction;

public class SpatialTransformHandler {

	public		void	objectFreeTranslation(Spatial cl_spatialSel, boolean b_mouseDown, Spatial ...cla_others) {
		if(cl_spatialSel != null) {
			// mouse has just been pressed
			if(!b_mouseDown) {
				SpatialSelectionHandler.initialiseUndoTranslation(cl_spatialSel, cla_others);
			}
			
			Vector3f		lcl_oldWorldLoc = cl_spatialSel.getWorldTranslation();
			Vector3f		lcl_newWorldLoc = CameraUtils.mostParallelCamPlaneIntersect(lcl_oldWorldLoc);
			if(lcl_newWorldLoc != null) {
				float		lf_xDiff = lcl_newWorldLoc.x - lcl_oldWorldLoc.x;
				float		lf_yDiff = lcl_newWorldLoc.y - lcl_oldWorldLoc.y;
				float		lf_zDiff = lcl_newWorldLoc.z - lcl_oldWorldLoc.z;
				
				if(SceneWorkerGlobals.inst().getIntegerSnapOn()) {
					lf_xDiff = (int)lf_xDiff;
					lf_yDiff = (int)lf_yDiff;
					lf_zDiff = (int)lf_zDiff;
				}
				
				cl_spatialSel.getLocalTranslation().addLocal(lf_xDiff, lf_yDiff, lf_zDiff);
				cl_spatialSel.updateGeometricState(0, true);
				
				for(Spatial lcl_other : cla_others) {
					lcl_other.getLocalTranslation().addLocal(lf_xDiff, lf_yDiff, lf_zDiff);
					lcl_other.updateGeometricState(0, true);
				}
			}
		}
	}
	
	public		void	objectFreeTranslation(Spatial cl_spatialSel, boolean b_mouseDown, Vector3f cl_unit, Spatial ...cla_others) {
		if(cl_spatialSel != null) {
			// mouse has just been pressed
			if(!b_mouseDown) {
				SpatialSelectionHandler.initialiseUndoTranslation(cl_spatialSel, cla_others);
			}
			
			Vector3f		lcl_oldWorldLoc = cl_spatialSel.getWorldTranslation();
			Vector3f		lcl_newWorldLoc = CameraUtils.mostParallelCamPlaneIntersect(lcl_oldWorldLoc);
			if(lcl_newWorldLoc != null) {
				float		lf_xDiff = (lcl_newWorldLoc.x - lcl_oldWorldLoc.x) * cl_unit.x;
				float		lf_yDiff = (lcl_newWorldLoc.y - lcl_oldWorldLoc.y) * cl_unit.y;
				float		lf_zDiff = (lcl_newWorldLoc.z - lcl_oldWorldLoc.z) * cl_unit.z;
				
				if(SceneWorkerGlobals.inst().getIntegerSnapOn()) {
					lf_xDiff = (int)lf_xDiff;
					lf_yDiff = (int)lf_yDiff;
					lf_zDiff = (int)lf_zDiff;
				}
				
				cl_spatialSel.getLocalTranslation().addLocal(lf_xDiff, lf_yDiff, lf_zDiff);
				cl_spatialSel.updateGeometricState(0, true);
				
				for(Spatial lcl_other : cla_others) {
					lcl_other.getLocalTranslation().addLocal(lf_xDiff, lf_yDiff, lf_zDiff);
					lcl_other.updateGeometricState(0, true);
				}
			}
		}
	}
	
	public	void	objectTranslationInputHandler(Spatial cl_spatialSel, boolean b_mouseDown, Vector3f cl_txMod, Vector2f cl_mouseMod, Spatial ...cla_others) {
		if(cl_spatialSel != null) {
			if(!b_mouseDown) {
				SpatialSelectionHandler.initialiseUndoTranslation(cl_spatialSel, cla_others);
			}
			
			float		lf_delta;
			if(cl_spatialSel.getRenderQueueMode() != Renderer.QUEUE_ORTHO) {
				float		lf_dist = (CameraUtils.distToCam(cl_spatialSel) / 200f);
				lf_delta = (MouseInput.get().getXDelta() * lf_dist * cl_mouseMod.x) + (MouseInput.get().getYDelta() * lf_dist * cl_mouseMod.y);
			} else {
				lf_delta = (MouseInput.get().getXDelta() * cl_mouseMod.x) + (MouseInput.get().getYDelta() * cl_mouseMod.y);
			}
			
			if(SceneWorkerGlobals.inst().getIntegerSnapOn()) {
				lf_delta = (int)lf_delta;
			}
			
			cl_spatialSel.getLocalTranslation().x += (lf_delta * cl_txMod.x);
			cl_spatialSel.getLocalTranslation().y += (lf_delta * cl_txMod.y);
			cl_spatialSel.getLocalTranslation().z += (lf_delta * cl_txMod.z);
			cl_spatialSel.updateGeometricState(0, true);
			
			for(Spatial lcl_spatial : cla_others) {
				lcl_spatial.getLocalTranslation().x += (lf_delta * cl_txMod.x);
				lcl_spatial.getLocalTranslation().y += (lf_delta * cl_txMod.y);
				lcl_spatial.getLocalTranslation().z += (lf_delta * cl_txMod.z);
				lcl_spatial.updateGeometricState(0, true);
			}
		}
	}
	
	public	void	objectRotate(Spatial cl_spatialSel, boolean b_mouseDown, final Vector3f cl_unitVector, Spatial ...cla_others) {
		if(cl_spatialSel != null) {
			if(!b_mouseDown) {
				SceneWorkerAppUndoManager.inst().addUndoAction(new SpatialRotationUndoAction(cl_spatialSel, cl_spatialSel.getLocalRotation().clone()));
			}
			
			Quaternion		lcl_rot = cl_spatialSel.getLocalRotation();
			Quaternion		lcl_qNew = new Quaternion();
			lcl_qNew.fromAngleAxis((MouseInput.get().getXDelta() * SceneWorkerInputHandler.ROTATE_FACTOR), cl_unitVector);
			lcl_qNew.multLocal(lcl_rot);
			lcl_rot.set(lcl_qNew);
			cl_spatialSel.updateGeometricState(0, true);
		}
	}
	
	public	void	objectScale(Spatial cl_spatialSel, boolean b_mouseDown, final Vector3f cl_unitVector) {
		if(cl_spatialSel != null) {
			if(!b_mouseDown) {
				SceneWorkerAppUndoManager.inst().addUndoAction(new SpatialScaleUndoAction(cl_spatialSel, cl_spatialSel.getLocalScale()));
			}
			
			//System.out.println(MouseInput.get().getXDelta() + " " + MouseInput.get().getYDelta());
			
			Vector3f		lcl_scale = cl_spatialSel.getLocalScale();
			float		lf_xDelta = cl_unitVector.x * (MouseInput.get().getXDelta() * 0.01f);
			float		lf_yDelta = cl_unitVector.y * (MouseInput.get().getYDelta() * 0.01f);
			float		lf_zDelta = cl_unitVector.z * (MouseInput.get().getXDelta() * 0.01f);
			
			lcl_scale.x += lf_xDelta;
			lcl_scale.y += lf_yDelta;
			lcl_scale.z += lf_zDelta;
			
			if(lcl_scale.x <= 0.0f) {
				lcl_scale.x = 0.01f;
			}
			
			if(lcl_scale.y <= 0.0f) {
				lcl_scale.y = 0.01f;
			}
			
			if(lcl_scale.z <= 0.0f) {
				lcl_scale.z = 0.01f;
			}
			
			cl_spatialSel.updateGeometricState(0, true);
		}
	}
}
